#pragma once
#include <iostream>
#include <memory>
#include <unordered_map>
#include "Connection.hpp"
#include "Epoller.hpp"
class Connection;
class Reactor
{
    static const int revs_num = 128;

public:
    Reactor()
        : _epoller_ptr(std::make_unique<Epoller>()), _isrunning(false)
    {
    }

    void Loop()
    {
        if (IsConnectionEmpty())
            return;

        _isrunning = true;
        int timeout = -1;
        while (true)
        {
            int n = LoopOnce(timeout);
            Dispatcher(n);
        }

        _isrunning = false;
    }

    // 该接口要把所有新到来的连接，写透到epoll内核中去
    void AddConnection(std::shared_ptr<Connection> &con)
    {
        // 不要重复添加conn
        // conn和它关心的事件写透到内核中去
        if (IsConnectionExists(con))
        {
            LOG(LogLevel::WARNING) << "conn is exists: " << con->GetSockFd();
            return;
        }

        uint32_t event = con->GetEvent();
        int fd = con->GetSockFd();
        _epoller_ptr->AddEvent(fd, event);
        con->SetOwner(this);
        _connections[fd] = con;
    }

    ~Reactor() {}

private:
    // epoll模型
    std::unique_ptr<Epoller> _epoller_ptr;
    // listener模块
    // std::shared_ptr<Listener> _listener_ptr;
    // 管理所有的connection，本质管理fd
    std::unordered_map<int, std::shared_ptr<Connection>> _connections;
    // 是否启动
    bool _isrunning;
    // 就绪事件集合
    struct epoll_event _revs[revs_num];

private:
    bool IsConnectionExistsHelper(int sockfd)
    {
        auto iter = _connections.find(sockfd);
        if (iter == _connections.end())
            return false;
        else
            return true;
    }
    bool IsConnectionExists(const std::shared_ptr<Connection> &conn)
    {
        return IsConnectionExistsHelper(conn->GetSockFd());
    }
    bool IsConnectionExists(int sockfd)
    {
        return IsConnectionExistsHelper(sockfd);
    }
    bool IsConnectionEmpty()
    {
        return _connections.empty();
    }

    int LoopOnce(int timeout)
    {
        return _epoller_ptr->WaitEvent(_revs, revs_num, timeout);
    }
    void Dispatcher(int revnum)
    {
        for (int i = 0; i < revnum; i++)
        {

            int sockfd = _revs[i].data.fd;    // 就绪的文件描述符
            uint32_t event = _revs[i].events; // 文件对应的关心事件
            if (event & EPOLLERR)
                event |= (EPOLLIN | EPOLLOUT); // 1. 将所有的异常处理，统一转化成IO错误
            if (event & EPOLLHUP)
                event |= (EPOLLIN | EPOLLOUT);

            if (event & EPOLLIN)
            {
                // 读写事件就绪之后就不用关心是否是异常
                if (IsConnectionExists(sockfd))
                    _connections[sockfd]->Recver();
            }
            if (event & EPOLLOUT)
            {
                if (IsConnectionExists(sockfd))
                    _connections[sockfd]->Sender();
            }
        }
    }

public:
    void EnableReadWrite(int sockfd, bool enableread, bool enablewrite)
    {
        if (!IsConnectionExists(sockfd))
        {
            LOG(LogLevel::WARNING) << "EnableReadWrite,conn is not exists: " ;
            return;
        }
         // 1. 修改当前sockfd对应的connection关心的事件
        uint32_t new_event = (EPOLLET | (enableread ? EPOLLIN : 0) | (enablewrite ? EPOLLOUT:0));
        _connections[sockfd]->SetEvent(new_event);

        // 2. 写透到内核，调整sockfd对特定事件的关心
        _epoller_ptr->ModEvent(sockfd, new_event);
    }
};